﻿//*** Guidance generated code ***//
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Net.Mime;
using System.Text;
using System.Web.Mvc;

using ProjectBase.Core;
using ProjectBase.Core.Web;

namespace ProjectBase.Mvc.Views
{
    /// <summary>
    ///     Result which can be directly used for returning the file.
    ///
    ///     thanks to: //http://www.thuban.org/Blog
    /// </summary>
    public class FileCoreResult : ActionResult
    {
        #region members
        Encoding _contentEncoding;
        string _contentType;
        IEnumerable<byte> _data;
        string _fileName;
        #endregion members

        #region constructor
        /// <summary>
        ///     Returns FileResult with provided name, type and based on XDocument
        /// </summary>
        /// <param name = "model">Model with all needed information</param>
        public FileCoreResult(IExportModel model)
        {
            Contract.Requires(model.Is(), " Sorry, model was null, cannot proceed ");
            Contract.Requires(model.XDocument.Is() || model.DataOutput.Is(),
                " XDocument was null. Cannot proceed to send FileResult ");

            var extension = model.FileExtension.Is()
                                ? (model.FileExtension.StartsWith(".", StringComparison.OrdinalIgnoreCase)
                                       ? string.Empty
                                       : ".") + model.FileExtension
                                : string.Empty;
            _fileName = model.FileName
                        + DateTime.Now.GetHashCode()
                        + extension;
            _contentType = model.ContentType;
            _contentEncoding = model.Encoding;
            if (model.XDocument.Is())
            {
                var document = model.XDocument.ToString();
                if (!document.StartsWith("<?xml", StringComparison.OrdinalIgnoreCase))
                {
                    document = "<?xml version=\"1.0\" encoding=\"utf-8\"?>" + document;
                }
                _data = new UTF8Encoding()
                    .GetBytes(document.ToCharArray())
                    .ToArray();
            }
            else
            {
                _data = model.DataOutput;
            }
        }
        #endregion constructor

        #region public
        /// <summary>
        ///     MVC key point method, which provides the output to the client
        /// </summary>
        /// <param name = "context"></param>
        public override void ExecuteResult(ControllerContext context)
        {
            var response = context.HttpContext.Response;

            response.Clear();
            response.ClearContent();

            response.ContentType = MediaTypeNames.Text.Plain;
            if (ContentType.IsNotEmpty())
            {
                response.ContentType = ContentType;
            }

            response.ContentEncoding = ContentEncoding ?? Encoding.Default;

            if (FileName.IsNotEmpty())
            {
                response.AppendHeader("content-disposition", "attachment; filename=" + FileName);
            }

            if (Headers.Is())
            {
                foreach (var header in Headers)
                {
                    response.AppendHeader(header.Key, header.Value);
                }
            }

            if (Data.Is())
            {
                response.BinaryWrite(Data.ToArray());
            }
        }
        #endregion public

        #region properties
        /// <summary>
        ///     The file itself in binnary
        /// </summary>
        public virtual IEnumerable<byte> Data
        {
            get { return _data; }
            set { _data = value; }
        }

        /// <summary>
        ///     Name for client
        /// </summary>
        public virtual string FileName
        {
            get { return _fileName; }
            set { _fileName = value; }
        }

        /// <summary>
        ///     Crucial Encoding with
        /// </summary>
        public virtual Encoding ContentEncoding
        {
            get { return _contentEncoding; }
            set { _contentEncoding = value; }
        }

        /// <summary>
        ///     Helps browsers to decide but extension is usually more important
        /// </summary>
        public virtual string ContentType
        {
            get { return _contentType; }
            set { _contentType = value; }
        }

        /// <summary>
        ///     Header information
        /// </summary>
        public virtual IDictionary<string, string> Headers { get; set; }
        #endregion properties
    }
}